#include "contact.h"

//根据姓名排序
int cmp_by_name(const void* p1, const void* p2)
{
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}

//根据姓名进行查找 查找到则返回下标,查找不到则返回-1
//加上static 只在本文件能被使用
static int Find_by_name(const Contact* pc, const char* name)
{
	int i = 0;

	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}

	return -1;
}

//检查空间容量是否满,若满并且扩容失败返回0, 若没满或者扩容成功返回1
static int CheckCapacity(Contact* pc)
{
	assert(pc);

	if (pc->capacity == pc->count)
	{
		//扩容
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + INC_SZ));
		
		if (ptr != NULL)
		{
			pc->data = ptr;
			ptr = NULL;
			pc->capacity += INC_SZ;
			printf("扩容成功.\n");
			return 1;
		}
		else
		{
			perror("CheckCapacity");
			return 0;
		}
	}
	return 1;
}

static void LoadContact(Contact* pc)
{
	FILE* fp = fopen("ContactInfo", "rb");
	if(fp == NULL)
	{
		perror("LoadContact");
		return;
	}
	
	//创建临时变量
	PeoInfo tmp = {0, };
	while (fread(&tmp, sizeof(PeoInfo), 1, fp))
	{
		if (0 == CheckCapacity(pc))
			return;
		pc->data[pc->count++] = tmp;
	}
	//关闭文件
	fclose(fp);
	fp = NULL;
}
			
//初始化一个通讯录
void InitContact(Contact* pc)
{
	assert(pc);

	//给通讯录的存放联系人的地方分配空间
	pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));

	if (pc->data == NULL)
	{
		perror("InitContact:");
		return;
	}

	//将通讯录的容量置为初始值
	pc->capacity = DEFAULT_SZ;
	//将通讯录中的计数初始化为0
	pc->count = 0;

	//从文件中加载数据到程序中
	LoadContact(pc);
}

//添加通讯录信息
void AddContact(Contact* pc)
{
	assert(pc);

	if (0 == CheckCapacity(pc))
	{
		printf("通讯录已满,不能添加信息.\n");
		system("PAUSE");
		system("CLS");
		return;
	}

	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &pc->data[pc->count].age);
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->count].addr);

	pc->count++;
	printf("添加成功!\n");

}

//显示通信录信息
void ShowContact(const Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,显示失败.\n");
		return;
	}

	int i = 0;

	printf("%-20s%-5s%-10s%-12s%-50s\n\n", "姓名", "年龄", "性别", "电话", "地址");

	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s%-5d%-10s%-12s%-50s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}
}

//删除通讯录信息(根据姓名删除)
void DelContact(Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,删除失败.\n");
		return;
	}

	//输入
	char name[MAX_NAME] = { 0, };
	printf("请输入要删除的姓名:>");
	scanf("%s", name);

	//查找
	int pos = Find_by_name(pc, name);

	if (-1 == pos)
	{
		printf("没有找到该姓名,删除失败.\n");
		return;
	}

	//删除元素, pos位置后面的元素向前移动
	int i = 0;
	for (i = pos + 1; i < pc->count; i++)
	{
		pc->data[i - 1] = pc->data[i];
	}
	pc->count--;

	printf("删除成功.\n");
}

//查找通讯录信息(根据姓名查找)
void SearchContact(const Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,查找失败.\n");
		return;
	}

	//输入
	char name[MAX_NAME] = { 0, };
	printf("请输入要查找的姓名:>");
	scanf("%s", name);

	//查找
	int pos = Find_by_name(pc, name);

	if (-1 == pos)
	{
		printf("没有找到该姓名,查找失败.\n");
		return;
	}

	printf("%-20s%-5s%-10s%-12s%-50s\n\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-10s%-12s%-50s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);

	printf("查找成功.\n");
}

//修改通讯录信息(根据姓名修改)
void ModifyContact(Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,修改失败.\n");
		return;
	}

	//输入
	char name[MAX_NAME] = { 0, };
	printf("请输入要修改的姓名:>");
	scanf("%s", name);

	//查找
	int pos = Find_by_name(pc, name);

	if (-1 == pos)
	{
		printf("没有找到该姓名,修改失败.\n");
		return;
	}

	//修改
	printf("请输入修改后的信息.\n");
	printf("请输入姓名:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &pc->data[pos].age);
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);

	printf("修改成功.\n");
}

//清空通讯录信息
void ClearContact(Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,清空失败.\n");
		return;
	}

	InitContact(pc);
	printf("清空成功.\n");
}

//对通信录信息进行排序
void SortContact(Contact* pc)
{
	assert(pc);

	if (0 == pc->count)
	{
		printf("通讯录为空,排序失败.\n");
		return;
	}

	//排序
	qsort(pc, pc->count, sizeof(PeoInfo), cmp_by_name);

	printf("排序成功.\n");
}

//销毁通信录,将空间归还给操作系统
void DestroyContact(Contact* pc)
{
	assert(pc);

	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->count = 0;
}

//保存数据到文件中
void SaveContact(const Contact* pc)
{
	FILE* fp = fopen("ContactInfo", "wb");

	if (fp == NULL)
	{
		perror("SaveContact");
		return;
	}

	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, fp);
	}

	//关闭文件
	fclose(fp);
	fp = NULL;
}	

